package com.dq.service.org.impl;

import com.alibaba.fastjson.JSONObject;
import com.dq.context.Constant;
import com.dq.domain.sys.role.SysRole;
import com.dq.domain.sys.role.SysUserRole;
import com.dq.exception.customException.AdminException;
import com.dq.exception.customException.DqRuntimeException;
import com.dq.controller.in.org.OrgQuery;
import com.dq.controller.in.base.BaseAdminQuery;
import com.dq.utils.HttpUtil;
import com.dq.utils.PasswordUtil;
import com.dq.domain.base.AbstractEntity;
import com.dq.domain.base.impl.BaseDaoImpl;
import com.dq.domain.sys.menu.SysMenu;
import com.dq.domain.org.Org;
import com.dq.domain.sys.section.SysSection;
import com.dq.domain.sys.user.user.*;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.repository.BaseRepositories;
import com.dq.service.org.OrgService;
import com.dq.utils.BeanNullUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liuhui
 * @date 2019/12/2 0002 18:08:13
 */
@Service
public class OrgServiceImpl extends BaseRepositories implements OrgService {
    @PersistenceContext
    private EntityManager entityManager;

    /**
     * 删除门店， 同时删除门店账号
     * @param id
     * @throws AdminException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) throws AdminException {
        Org org = dao.get(Org.class, id);
        if (null == org) {
            throw new AdminException("门店信息不存在");
        }
//        // 获取门店下所有员工 ---- staffuser
//        List<StaffUser> staffUsers = staffUserRepository.findByDeletedAndSection(false, org);
//        if(staffUsers != null && staffUsers.size() > 0) {
//            throw new AdminException("需先对门店下员工进行转移");
//        }
        // 获取门店下所有员工 ---- bossuser
        List<BossUser> staffUsers = bossUserRepository.findByDeletedFalseAndSection(org);
        if(staffUsers != null && staffUsers.size() > 0) {
            throw new AdminException("需先对门店下员工进行转移");
        }
        // 获取门店下所有顾客
        List<WxUser> wxusers = wxUserRepository.findByDeletedAndSection(false, org);
        if(wxusers != null && wxusers.size() > 0) {
            throw new AdminException("需先对门店下顾客进行转移");
        }

        org.setDeleted(true);
        org.setLastModifyTime(System.currentTimeMillis());
        SysUser user = sysUserService.getUser();
        org.setUpdateUser(user);
        orgRepository.save(org);
    }

    @Override
    public Org save(Org org) throws AdminException {
        if (org.getParentId() == null) {
            throw new AdminException("请选择上级部门");
        }

        // 获取 祖级列表, 并对父级对象验证
        getAncestors(org);
        // 重复对象验证
        repetitionObjectBySave(org);

        BossUser shopManage = null;
        if(org.getShopManagerId() != null) {
            shopManage = dao.get(BossUser.class, org.getShopManagerId());
            if(shopManage == null) {
                throw new AdminException("关联店长不存在");
            }
            if(shopManage.getSection() instanceof Org) {
                Org shopManageOrg = orgRepository.findByDeletedFalseAndShopManager(shopManage);
                if(shopManageOrg != null) {
                    throw new AdminException("此店长已关联过其他店铺");
                }
            }
            org.setShopManager(shopManage);
        }else {
//            throw new AdminException("未关联店长");
        }
//        if(org.getProvincialManagerId() != null) {
//            BossUser provincialManager = dao.get(BossUser.class, org.getProvincialManagerId());
//            if(provincialManager == null) {
//                throw new AdminException("关联所属省总不存在");
//            }
//            org.setProvincialManager(provincialManager);
//        }else {
//            throw new AdminException("未关联所属省总");
//        }

        // 初始化对象
        org = initObject(org);

        // 设置经纬度
        String adrAll = org.getProvince() + org.getCity() + org.getDistrict() + org.getAddress();
        JSONObject json = adr2LatLng(adrAll);
        org.setLng(new BigDecimal(json.get("lng").toString()));
        org.setLat(new BigDecimal(json.get("lat").toString()));

        org = orgRepository.save(org);

        if(shopManage != null) {
            shopManage.setSection(org);
            shopManage = bossUserRepository.save(shopManage);

            setShopMnageRole(shopManage);
        }

        // 生成门店初始 顾客， 用于第一批用户授权登录
        initialOrgWxUser(org);

        return org;
    }


    /**
     * 腾讯API
     *  地址解析: 地址转坐标
     */
    public JSONObject adr2LatLng(String adrAll) {
        JSONObject returnJson = new JSONObject();
        if(StringUtils.isBlank(adrAll)) {
            throw new AdminException("[腾讯API-地址转坐标] - 需解析地址为空");
        }
        try {
            adrAll = URLEncoder.encode(adrAll,"utf-8");
        }catch (Exception e) {
            e.printStackTrace();
            throw new AdminException(String.format("[腾讯API-地址转坐标] - 需解析地址编码异常: [%s]", adrAll));
        }

        // 排序后参数拼接
        String params = "address=" + adrAll +  "&key=" + Constant.TX_KEY;

        // 请求路径(无域名) + ”?” + 排序后参数拼接
        String url_portion = Constant.TX_ADR_2_LNG_URL + "?" + params;

        String signOriginal = URLDecoder.decode(url_portion + Constant.TX_WEBSERVVICE_KEY);
        String sign = PasswordUtil.md5Hex(signOriginal);
        System.out.println("signOriginal: " + signOriginal);
        System.out.println(sign);

        // 完整请求url: 域名 + 请求路径(无域名) + ”?” + 排序后参数拼接 + 签名
        String url = Constant.TX_HTTP_URL + url_portion + "&sig=" + sign;
        System.out.println(url);

        JSONObject jsonObject = HttpUtil.httpsGetRequest(url, null, Constant.TX_CODE, Constant.TX_MSG);
        if(jsonObject.get(Constant.TX_CODE).toString().equals(Constant.TX_CODE_VALUE)) {
            JSONObject result = jsonObject.getJSONObject("result");
            JSONObject location = result.getJSONObject("location");
            BigDecimal lng = new BigDecimal(location.get("lng").toString());
            BigDecimal lat = new BigDecimal(location.get("lat").toString());
            returnJson.put("lng", lng);
            returnJson.put("lat", lat);
        }else {
            System.out.println(jsonObject);
           throw new AdminException("[腾讯API-地址转坐标] - 异常: " + jsonObject.get(Constant.TX_MSG).toString());
        }

        return returnJson;
    }

    /**
     * 保存时 重复对象验证
     */
    @Override
    public void repetitionObjectBySave(SysSection section) {
        // 简称是否存在, 不包括删除的
        SysSection get = sysSectionRepository.findByDeletedIsFalseAndSimpleName(section.getSimpleName());
        if(get != null && get.getId() != null) {
            throw new DqRuntimeException("简称已经存在");
        }
        if(StringUtils.isBlank(section.getSectionCode())) {
            section.setSectionCode(AbstractEntity.generyDatetimeAndRandomNum(Constant.ORDERS_SUFF_COUNT));
        }else {
            // 编号是否存在, 不包括删除的
            SysSection getByCode = sysSectionRepository.findByDeletedIsFalseAndSectionCode(section.getSectionCode());
            if(getByCode != null && getByCode.getId() != null) {
                throw new DqRuntimeException("编号已经存在, 部门名称: " + getByCode.getSimpleName());
            }
        }
    }
    /**
     * 获取 祖级列表, 并对父级对象验证
     */
    @Override
    public void getAncestors(SysSection section) {
        String ancestors = "";
        if (section.getParentId() != null) {
            SysSection parent = dao.get(SysSection.class, section.getParentId());
            if (null == parent || parent.getId() == null) {
                throw new AdminException("无效的父级机构");
            }
            // 如果父节点不为正常状态,则不允许新增子节点
            if (parent.getStatus().toString().equals(SysMenu.Status.off.toString())) {
                throw new AdminException("父级机构停用，不允许新增");
            }

            if(StringUtils.isNotBlank(parent.getAncestors())) {
                ancestors = parent.getAncestors();
            }
            if(StringUtils.isNotBlank(ancestors)) {
                ancestors = ancestors + "," + parent.getId();
            }else {
                ancestors = parent.getId().toString();
            }


            section.setParent(parent);
        }
        section.setAncestors(ancestors);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Org update(Org org) throws AdminException {
        // 重复对象验证
        repetitionObject(org);

        Org one = dao.get(Org.class, org.getId());
        if (null == one) {
            throw new AdminException("修改门店不存在");
        }

        BossUser shopManage = null;
        if(org.getShopManagerId() != null) {
            if(one.getShopManager() == null || one.getShopManager().getId() == null) {
                shopManage = getShopMange(org);
            }else {
                if(!org.getShopManagerId().toString().equals(one.getShopManager().getId().toString())) {
                    shopManage = getShopMange(org);
                }
            }
        }
//        if(org.getProvincialManagerId() != null) {
//            if(!org.getProvincialManagerId().toString().equals(one.getProvincialManager().getId().toString())) {
//                BossUser provincialManager = dao.get(BossUser.class, org.getProvincialManagerId());
//                if(provincialManager == null) {
//                    throw new AdminException("关联所属省总不存在");
//                }
//                org.setProvincialManager(provincialManager);
//            }
//        }
        BeanUtils.copyProperties(org, one, BeanNullUtil.getNullPropertyNames(org));

        ifObject(one);

        SysUser user = sysUserService.getUser();
        one.setUpdateUser(user);

        // 设置经纬度
        String adrAll = one.getProvince() + one.getCity() + one.getDistrict() + one.getAddress();
        JSONObject json = adr2LatLng(adrAll);
        one.setLng(new BigDecimal(json.get("lng").toString()));
        one.setLat(new BigDecimal(json.get("lat").toString()));
        System.out.println(json);

        one = orgRepository.save(one);
        if(shopManage != null) {
            shopManage.setSection(one);
            shopManage = bossUserRepository.save(shopManage);

            setShopMnageRole(shopManage);
        }
        return one;
    }

    /**
     * 门店分配管理店长, 为所选用户分配店长角色
     * @param shopManage
     */
    private void setShopMnageRole(BossUser shopManage) {
        List<SysUserRole> userRoleListole = sysUserRoleRepository.findByDeletedIsFalseAndSysUserAndSysRoleCode(shopManage, Constant.ROLE_CODE_LIST.get(3));
        if (userRoleListole == null || userRoleListole.size() <= 0) {
            SysUserRole sysUserRole = new SysUserRole();
            List<SysRole> roleList = sysRoleRepository.findByDeletedFalseAndCodeOrderByCreateTimeDesc(Constant.ROLE_CODE_LIST.get(3));
            if (roleList == null || roleList.size() <= 0) {
                throw new AdminException("角色获取异常, 未初始化对应角色");
            }
            sysUserRole.setSysRole(roleList.get(0));
            sysUserRole.setSysUser(shopManage);
            sysUserRoleRepository.save(sysUserRole);
        }
    }

    private BossUser getShopMange(Org org) {
        BossUser shopManage;
        shopManage = dao.get(BossUser.class, org.getShopManagerId());
        if (shopManage == null) {
            throw new AdminException("关联店长不存在");
        }
        org.setShopManager(shopManage);
        if (!org.getId().toString().equals(shopManage.getSection().getId().toString())) {
            if (shopManage.getSection() instanceof Org) {
                Org shopManageOrg = orgRepository.findByDeletedFalseAndShopManager(shopManage);
                if(shopManageOrg != null) {
                    throw new AdminException("此店长已关联过其他店铺");
                }
            }
        } else {
            shopManage = null;
        }
        return shopManage;
    }

    /**
     * 修改时 重复对象验证
     */
    @Override
    public void repetitionObject(@Valid SysSection section) {
        // 简称是否存在, 不包括删除的
        SysSection get = sysSectionRepository.findByDeletedIsFalseAndSimpleName(section.getSimpleName());
        if(get != null && get.getId() != null) {
            if(!get.getId().toString().equals(section.getId().toString())) {
                throw new DqRuntimeException("简称已经存在");
            }
        }
        // 编号是否存在, 不包括删除的
        SysSection getByCode = sysSectionRepository.findByDeletedIsFalseAndSectionCode(section.getSectionCode());
        if(getByCode != null && getByCode.getId() != null) {
            if(!getByCode.getId().toString().equals(section.getId().toString())) {
                throw new DqRuntimeException("编号已经存在, 部门名称: " + getByCode.getSimpleName());
            }
        }
    }

    /**
     * 对象初始化
     */
    @Override
    public Org initObject(Org org) throws AdminException {
        if(org.getStatus() == null) {
            org.setStatus(SysMenu.Status.on);
        }
        if(StringUtils.isBlank(org.getSectionCode())) {
            org.setSectionCode(Org.generyDatetimeAndRandomNum(Constant.ORDERS_SUFF_COUNT));
        }
        if(org.getBedNum() == null) {
            org.setBedNum(0L);
        }
        // 费控判断
        ifObject(org);

        SysUser user = sysUserService.getUser();
        org.setCreateUser(user);
        org.setUpdateUser(user);

        return org;
    }

    private void ifObject(Org org) throws AdminException {
        if(StringUtils.isBlank(org.getSimpleName())) {
            throw new AdminException("门店名称为空");
        }
//        if(org.getShopManager() == null) {
//            throw new AdminException("负责店长为空");
//        }
//        if(org.getProvincialManager() == null) {
//            throw new AdminException("所属省总为空");
//        }
//        if(StringUtils.isBlank(org.getLegalName())) {
//            throw new AdminException("法人名称为空");
//        }
//        if(StringUtils.isBlank(org.getLegalCardNo())) {
//            throw new AdminException("身份证号为空");
//        }
        if(StringUtils.isBlank(org.getContaceMobile())) {
            throw new AdminException("手机号为空");
        }
//        if(StringUtils.isBlank(org.getFixedPhone())) {
//            throw new AdminException("固话为空");
//        }
        if(StringUtils.isBlank(org.getProvince()) || StringUtils.isBlank(org.getCity()) || StringUtils.isBlank(org.getDistrict())) {
            throw new AdminException("所属区域(省市区)为空");
        }
        if(StringUtils.isBlank(org.getAddress())) {
            throw new AdminException("详细地址为空");
        }
        if(org.getStatus() == null) {
            throw new AdminException("状态为空");
        }
        if(StringUtils.isBlank(org.getSectionCode())) {
            throw new AdminException("编号");
        }
    }

    /**
     * 获取 负责的门店列表 - 分页
     */
    @Override
    public List<Org> listByLogin(OrgQuery orgQuery) throws AdminException {
        Map<String, Object> query = creatQuery(orgQuery);

        return dao.find(dao.query2Hql(Org.class, query), query);
    }
    @Override
    public Long counteByLogin(OrgQuery orgQuery) throws AdminException {
        Map<String, Object> query = creatQuery(orgQuery);

        return dao.count(dao.count2Hql(Org.class, query), query);
    }
    public Map<String, Object>  creatQuery(OrgQuery orgQuery) throws AdminException {
        Map<String, Object> query = orgQuery.parseMap();

        if(orgQuery.getOrgId() != null) {
            query.put("id", orgQuery.getOrgId());
            query.remove("orgId");
        }else {
            // 只显示负责门店信息
            List<Org> orgList = getListAllByUser();
            if(orgList == null || orgList.size() <= 0) {
                query.put("id", -1L);
            }else {
                List<Long> idsInList = new ArrayList<>();
                for (Org org : orgList) {
                    idsInList.add(org.getId());
                }
                query.put("id" + BaseDaoImpl.inSqlStr, idsInList);
            }
        }

        if(orgQuery.getProvincialManagerId() != null) {
            List<Long> list = new ArrayList<>();
            list.add(orgQuery.getProvincialManagerId());
            List<SysSection> sectionList = dao.findBySql(SysSection.class, String.format("SELECT t.* FROM sys_section t WHERE FIND_IN_SET (%s, t.ancestors)",orgQuery.getProvincialManagerId()));
            for (SysSection sysSection : sectionList) {
                list.add(sysSection.getId());
            }

            query.put("id" + BaseDaoImpl.inSqlStr, list);
//            query.put("provincialManager_id", orgQuery.getProvincialManagerId());
            query.remove("provincialManagerId");
        }
//        if(orgQuery.getParentId() != null) {
//            query.put("parent_id", orgQuery.getParentId());
//            query.remove("parentId");
//        }
        if(StringUtils.isNotBlank(orgQuery.getName())) {
            query.put("simpleName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(orgQuery.getName()));
            query.remove("name");
        }
        if(orgQuery.getTimeBegin() != null) {
            query.put("createTime" + BaseDaoImpl.gteSqlStr, orgQuery.getTimeBegin());
            query.remove("timeBegin");
        }
        if(orgQuery.getTimeEnd() != null) {
            query.put("createTime" + BaseDaoImpl.lteSqlStr, orgQuery.getTimeEnd());
            query.remove("timeEnd");
        }
        if(StringUtils.isNotBlank(orgQuery.getSearchBox())) {
            Map<String, Object> keyQuery = new HashMap<>(16);

            keyQuery.put("simpleName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(orgQuery.getSearchBox()));
            keyQuery.put("legalName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(orgQuery.getSearchBox()));
            keyQuery.put("legalCardNo" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(orgQuery.getSearchBox()));

            query.put("keyQuery" + BaseDaoImpl.orAndSqlStr, keyQuery);
            query.remove("searchBox");
        }
        return query;
    }

    @Override
    public List<Org> list(OrgQuery orgQuery) throws AdminException {
        Map<String, Object> query = creatQuery01(orgQuery);

        return dao.find(dao.query2Hql(Org.class, query), query);
    }
    @Override
    public Long count(OrgQuery orgQuery) throws AdminException {
        Map<String, Object> query = creatQuery01(orgQuery);

        return dao.count(dao.count2Hql(Org.class, query), query);
    }
    public Map<String, Object>  creatQuery01(OrgQuery orgQuery) throws AdminException {
        Map<String, Object> query = orgQuery.parseMap();

        if(StringUtils.isNotBlank(orgQuery.getName())) {
            query.put("simpleName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(orgQuery.getName()));
            query.remove("name");
        }

        return query;
    }

    /**
     * 获取 负责的门店列表  - 不分页
     */
    @Override
    public List<Org> getListAllByUser() throws AdminException {
        SysUser loginUser = sysUserService.getUserInSection();

        List<Org> orgList = new ArrayList<>();
        Map<String, Object> query = new HashMap<>(16);
        //            query.put("status", SysMenu.Status.on);

        if(sysRoleService.isRole(loginUser, 0)) {

        }else {
            if(loginUser.getSection() instanceof  Org) {
                query.put("id", loginUser.getSection().getId());
            }else {
                List<Long> list = new ArrayList<>();
                list.add(loginUser.getSection().getId());
                List<SysSection> sectionList = dao.findBySql(SysSection.class, String.format("SELECT t.* FROM sys_section t WHERE FIND_IN_SET (%s, t.ancestors)", loginUser.getSection().getId()));
                for (SysSection sysSection : sectionList) {
                    list.add(sysSection.getId());
                }
                query.put("id" + BaseDaoImpl.inSqlStr, list);
            }
        }

        orgList = dao.find(dao.query2Hql(Org.class, query), query);

        return orgList;
    }
    /**
     * 获取 负责的门店列表  - 不分页
     */
    @Override
    public String getIdListAllByUser() throws AdminException {
        // 只显示负责门店信息
        List<Org> orgList = getListAllByUser();

        if(orgList == null || orgList.size() <= 0) {
//            throw new AdminException("此账号无负责门店");
            return "";
        }
        StringBuilder orgIdsIn = new StringBuilder("");
        for (Org org : orgList) {
            orgIdsIn.append(org.getId()).append(",");
        }
        if(StringUtils.isNotBlank(orgIdsIn.toString())) {
            return "(" + orgIdsIn.toString().substring(0, orgIdsIn.toString().length() - 1) + ")";
        }else {
            return "";
        }
    }

    @Override
    public List<Org> getListAll() throws AdminException {
        return orgRepository.findByDeletedFalse();
    }

    /**
     * 生成门店初始 顾客， 用于第一批用户授权登录
     */
    @Override
    public WxUser initialOrgWxUser(Org org) {
        if(org == null || StringUtils.isBlank(org.getSectionCode())) {
            throw new AdminException("门店信息异常");
        }

        String userName = org.getSectionCode();
        WxUser user = wxUserRepository.getByUsername(userName);
        if(user == null) {
            System.out.println("----------------------> 生成初始二维码顾客");
            WxUser userSave = new WxUser();
            userSave.setDeleted(true);
            userSave.setSection(org);

            String openid = AbstractEntity.generyStrAndMstime("openid");
            userSave.setUnionid(openid);
            userSave.setOpenid(openid);

            userSave.setCardNo(AbstractEntity.generyStrAndMstime("HM"));
            userSave.setUsername(userName);
            userSave.setUserRealcName(userName);
            userSave.setLocalNickName(userName);

            //            userSave.setHeadImg();
//            userSave.setMobile();
            userSave.setInviteUser(null);
            userSave.setStatus(SysUser.Status.off);
            userSave.setShareCode(SysUser.generateShortUuid());
            userSave.setInviteTime(System.currentTimeMillis());
            userSave.setEntryTime(System.currentTimeMillis());
            userSave.setCustomerType(WxUser.CustomerType.active);
            user = wxUserRepository.save(userSave);
        }
        return user;
    }
}
